package com.wuhao.jdqlibnoui.utils

import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.ComponentName
import android.content.Context
import android.content.Context.BIND_AUTO_CREATE
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build
import android.os.IBinder
import android.os.ParcelUuid
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.core.app.ComponentActivity
import com.coder.vincent.smart_toast.SmartToast
import com.drake.channel.receiveEvent
import com.drake.channel.sendEvent
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.XXPermissions
import com.wuhao.jdqlibnoui.ble.UartServiceUART
import com.wuhao.jdqlibnoui.constants.AppConfig
import com.wuhao.jdqlibnoui.constants.BleConfig
import com.wuhao.jdqlibnoui.constants.BleConfig.RX_CHAR_UUID
import com.wuhao.jdqlibnoui.constants.BleConfig.RX_CHAR_UUID2
import com.wuhao.jdqlibnoui.constants.BleConfig.RX_CHAR_UUID_JGQ
import com.wuhao.jdqlibnoui.constants.BleConfig.RX_SERVICE_UUID
import com.wuhao.jdqlibnoui.constants.BleConfig.RX_SERVICE_UUID2
import com.wuhao.jdqlibnoui.constants.BleConfig.RX_SERVICE_UUID_JGQ
import com.wuhao.jdqlibnoui.constants.BleConfig.TX_CHAR_UUID
import com.wuhao.jdqlibnoui.constants.BleConfig.TX_CHAR_UUID2
import com.wuhao.jdqlibnoui.constants.BleConfig.TX_CHAR_UUID_JGQ
import com.wuhao.jdqlibnoui.data.BleBlulletEvent
import com.wuhao.jdqlibnoui.data.BleReceiveDataEvent
import com.wuhao.jdqlibnoui.data.BleStatusChangeEvent
import com.wuhao.jdqlibnoui.data.BleToConnectEvent
import com.wuhao.jdqlibnoui.interf.JdqCallBackNoUI
import com.wuhao.jdqlibnoui.interf.JdqCallback
import com.wuhao.jdqlibnoui.tts.SystemTTSRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.json.JSONObject
import kotlin.math.abs

@SuppressLint("MissingPermission")
class JdqLibUtilNoui(val context: Context, @SuppressLint("RestrictedApi") val activity: ComponentActivity) {
    var callback: JdqCallback? = null
    var isFirstShoot: Boolean = false
    var jdqNumber: Int = 0

    //临时存储，连接成功后使用
    private var temporarilyMac: String? = null
    private var temporarilyName: String? = null

    private val arrayPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        listOf(
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_SCAN,
            android.Manifest.permission.ACCESS_FINE_LOCATION
        )
    }
    else {
        listOf(
            android.Manifest.permission.BLUETOOTH,
            android.Manifest.permission.BLUETOOTH_ADMIN,
            android.Manifest.permission.ACCESS_FINE_LOCATION
        )
    }

    // 创建一个ActivityResultLauncher来启动蓝牙开启请求
    private var enableBtLauncher: ActivityResultLauncher<Intent>? = null
    private var bleAdapter: BluetoothAdapter? = null
    private fun getBluetoothAdapter(): BluetoothAdapter? {
        // 获取BluetoothManager系统服务
        val bluetoothManager: BluetoothManager =
            context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        // 通过BluetoothManager获取BluetoothAdapter
        val bluetoothAdapter: BluetoothAdapter? = bluetoothManager.adapter

        return bluetoothAdapter
    }

    private var mServiceUART: UartServiceUART? = null

    private val mServiceConnectionUART: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, rawBinder: IBinder) {
            mServiceUART = (rawBinder as UartServiceUART.LocalBinder).service
            LogUtil.error("onServiceConnected mService= $mServiceUART")
            if (mServiceUART?.initialize() != true) {
                LogUtil.error("Unable to initialize Bluetooth")
            }
        }

        override fun onServiceDisconnected(classname: ComponentName) {
            LogUtil.error("onServiceDisconnected ")
            mServiceUART = null
        }
    }

    private val tts = SystemTTSRepository(context)

    private fun checkPermissions(isNoUI: Boolean = false) {
        XXPermissions.with(context)
            .permission(
                arrayPermission
            ).request(object : OnPermissionCallback {
                override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
                    if (!allGranted) {
                        SmartToast.emotion().warning("权限未授予，无法使用蓝牙")
                    } else {
                        checkBleEnable(isNoUI)
                    }
                }

                override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
                    if (doNotAskAgain) {
                        SmartToast.emotion().warning("注意：被永久拒绝授权，会影响系统正常使用")
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(context, permissions)
                    } else {
                        SmartToast.emotion().warning("系统获取权限失败，会影响系统正常使用")
                    }
                }
            })
    }

    /**
     * 检查蓝牙是否可用、开关是否打开状态
     */
    private fun checkBleEnable(isNoUI: Boolean = false) {
        if (AppConfig.bleConnected) {
            //断开蓝牙确认
            SmartToast.emotion().warning("当前蓝牙处于连接状态")
            return
        }
        if (bleAdapter != null) {//是否开启蓝牙
            if (bleAdapter!!.isEnabled) {
                SmartToast.emotion().warning("蓝牙已开启，可正常使用")
            } else {
                // 蓝牙没有开启，请求用户开启
                val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                enableBtLauncher?.launch(enableBtIntent)
            }
        }
    }

    private fun bleDisConnectRefresh() {
        //更新UI
        AppConfig.bleName = null
        AppConfig.isConnectBle = false
        //本地调试数据
//        viewModel.addJDQDataToList(TimeUtils.getTime() + "--" + temporarilyName + " 已断开")
        //释放蓝牙资源
        mServiceUART?.close()
    }

    /**
     * 获取蓝牙设备名称
     * 1:记弹器   2：激光枪
     */
    private fun getDeviceName(): String {
        return when (AppConfig.bleType) {
            1 -> "记弹器"
            2 -> "激光枪"
            else -> "蓝牙设备"
        }
    }

    /**
     * 接收记弹器数据
     */
    fun receiveJdqData() {
        //接收连接事件
        activity.receiveEvent<BleToConnectEvent> { device ->
            //如果主界面没有打开，就不处理
            handleBleListClickEvent(device)
        }

        //接收蓝牙状态改变事件
        activity.receiveEvent<BleStatusChangeEvent> {
            LogUtil.info("BleStatusChangeEvent：${it.status}")
            when (it.status) {
                BleConfig.BLE_SERVICES_DISCOVERED -> {
                    mServiceUART?.enableTXNotification()
                    //dismissLoading()
                }
                //连接成功
                BleConfig.BLE_CONNECTED -> {
                    //设备名称
                    val name = getDeviceName()
                    val msg = "${name}连接成功"
                    SmartToast.emotion().success(msg)
                    callback?.onBlueConnected()
                }
                //断开连接
                BleConfig.BLE_DISCONNECTED -> {
                    val name = getDeviceName()
                    val msg = "${name}断开连接"
                    //语音播报
                    SmartToast.emotion().warning(msg)
                    bleDisConnectRefresh()
                    jdqNumber = 0
                    callback?.onBlueDisconnected()
                }
                //不支持蓝牙
                BleConfig.DEVICE_DOES_NOT_SUPPORT_UART -> {
                    //设备名称
                    val name = getDeviceName()
                    val msg = "${name}连接成功"
                    SmartToast.emotion().success(msg)
                }
            }
        }

        //接收蓝牙数据
        activity.receiveEvent<BleReceiveDataEvent> { bleData ->
            LogUtil.error("BleReceiveDataEvent：" + bleData.data)
            try {
                when (AppConfig.bleType) {
                    //记弹器数据
                    1 -> handleJiDanQiData(bleData.data)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    //最近一次播报时间
    private var lastCallTimeMillis = 0L
    private var lastReceiveTimeMillis = 0L

    /**
     * 处理蓝牙记弹器发送过来的数据
     * @param data 数据
     */
    fun handleJiDanQiData(data: String) {
        Log.e("jdqStr", data)
        if (data.startsWith("1,")) {//开枪
            val firstValue = data.substring(2)
            val mInt = if (firstValue.length < 9) {
                firstValue.toInt()
            } else {
                999999999
            }

            //满足条件：1.支持记弹器 3.超过阈值
            if (AppConfig.isSupportJdqMode && mInt > AppConfig.vibrationThreshold) {
                if (isFirstShoot == true) {
                    //忽略第一次(拉枪栓)
                    isFirstShoot = false
                    return
                }
                //记弹数量+1
                var shootCount = jdqNumber
                shootCount++
                jdqNumber = shootCount
                //开枪
//                shootFire(AppConfig.targetNumber.toInt())
                // 检查当前播报时间
                val currentTime = System.currentTimeMillis()
                //防止短时间内重复播报
                if (currentTime - lastReceiveTimeMillis >= AppConfig.shootInterval) {
                    //更新最后一次播报时间戳
                    lastReceiveTimeMillis = currentTime
                    //发送数据
                    sendEvent(BleBlulletEvent(jdqNumber))
                    callback?.onDataReceived("$jdqNumber")
                }
            }
        }
        else if (data.contains("alarm")) {//抬枪角度
            val jsonObject = JSONObject(data)
            val secondValue = jsonObject.getDouble("alarm")
            if (abs(secondValue) > AppConfig.angleThreshold) {
                // 检查当前播报时间
                val currentTime = System.currentTimeMillis()
                //防止短时间内重复播报
                if (currentTime - lastCallTimeMillis >= AppConfig.reportInterval) {
                    tts.playText("抬枪过高")
                    SmartToast.emotion().warning("抬枪过高")
                    //更新最后一次播报时间戳
                    lastCallTimeMillis = currentTime
                    callback?.onError("抬枪过高")
                }
            }
        }
        else if (data.startsWith("010203")) {
            //记弹数量+1
            var shootCount = jdqNumber
            shootCount++
            jdqNumber = shootCount
            // 检查当前播报时间
            val currentTime = System.currentTimeMillis()
            //防止短时间内重复播报
            if (currentTime - lastReceiveTimeMillis >= AppConfig.shootInterval) {
                //更新最后一次播报时间戳
                lastReceiveTimeMillis = currentTime
                //发送数据
                sendEvent(BleBlulletEvent(jdqNumber))
                callback?.onDataReceived("$jdqNumber")
            }
        }
    }

    /**
     * 处理蓝牙点击事件
     */
    private fun handleBleListClickEvent(device: BleToConnectEvent) {
        LogUtil.error("蓝牙点击 mac：" + device.mac)
        try {//可能会发送异常
            if (bleAdapter != null && bleAdapter!!.isEnabled) {
                AppConfig.bleTypeUUID = BleConfig.BLE_UUID
                if (device.name.startsWith("AE")) {//记弹器
                    if (!AppConfig.isSupportJdqMode) {//不支持记弹器
                        SmartToast.emotion().warning("当前模式不支持记弹器")
                        return
                    }
                    AppConfig.bleType = 1
                    AppConfig.bleServiceUUID = RX_SERVICE_UUID
                    AppConfig.bleNotifyUUID = TX_CHAR_UUID
                    AppConfig.bleWriteUUID = RX_CHAR_UUID
                    //binding.tvJiDanNum.visibility = View.VISIBLE
                } else if (device.name.startsWith("E104")) {
                    if (!AppConfig.isSupportJdqMode) {//不支持记弹器
                        SmartToast.emotion().warning("当前模式不支持记弹器")
                        return
                    }
                    AppConfig.bleType = 1
                    AppConfig.bleServiceUUID = RX_SERVICE_UUID2
                    AppConfig.bleNotifyUUID = TX_CHAR_UUID2
                    AppConfig.bleWriteUUID = RX_CHAR_UUID2
                    //binding.tvJiDanNum.visibility = View.VISIBLE
                } else {
                    AppConfig.bleType = 2
                    AppConfig.bleServiceUUID = RX_SERVICE_UUID_JGQ
                    AppConfig.bleNotifyUUID = TX_CHAR_UUID_JGQ
                    AppConfig.bleWriteUUID = RX_CHAR_UUID_JGQ
                    //binding.tvJiDanNum.visibility = View.GONE
                }

                temporarilyName = device.name
                temporarilyMac = device.mac
                //连接蓝牙
                mServiceUART?.let {
                    //showLoading()
                    mServiceUART!!.connect(device.mac)
                }
            } else {
                SmartToast.emotion().warning("蓝牙关闭，无法连接设备")
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 注册回调方法
     */
    fun registerCallBack(newCallback: JdqCallback){
        callback = newCallback
    }

    /**
     * 断开蓝牙连接
     */
    fun disConnect(){
        val result = mServiceUART?.disconnect()
        if (result == false) {
            bleDisConnectRefresh()
        }
    }
    /**
     * 关闭蓝牙连接、解绑
     */
    fun cleanResource() {
        mServiceUART?.disconnect()
        context.unbindService(mServiceConnectionUART)
        mServiceUART?.stopSelf()
        mServiceUART = null
        AppConfig.bleMac = null
        AppConfig.bleName = null
    }

    private var bleScanner: BluetoothLeScanner? = null
    private lateinit var scanCallback: ScanCallback
    private var deviceList: ArrayList<ScanResult> = arrayListOf()
    private var callBackNoUI: JdqCallBackNoUI? = null
    private var isScanning:Boolean = false

    fun initBlueNoUI(launcher: ActivityResultLauncher<Intent>){
        enableBtLauncher = launcher
        LogUtil.error("初始化蓝牙服务")
        val bindIntent = Intent(context, UartServiceUART::class.java)
        context.bindService(bindIntent, mServiceConnectionUART, BIND_AUTO_CREATE)
        bleAdapter = getBluetoothAdapter()
        receiveJdqData()

        checkPermissions(true)
        if (bleAdapter == null) {
            SmartToast.emotion().warning("本机不支持BLE")
            return
        }
        bleScanner = bleAdapter!!.bluetoothLeScanner

        // 设置扫描回调
        scanCallback = object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                super.onScanResult(callbackType, result)
                if (result.device?.name?.isNotEmpty() == true) {
                    processingResults(result)
                }
                if (deviceList.isEmpty()) {
                    callBackNoUI?.scanResult(500,deviceList)
                }else{
                    callBackNoUI?.scanResult(200,deviceList)
                }
            }

            override fun onBatchScanResults(results: List<ScanResult>) {
                deviceList.clear()
                for (result in results) {
                    deviceList.add(result)
                }
                callBackNoUI?.scanResult(200,deviceList)
            }

            override fun onScanFailed(errorCode: Int) {
                super.onScanFailed(errorCode)
                callBackNoUI?.scanResult(500,deviceList)
            }
        }
    }
    /**
     * 更新蓝牙
     */
    private fun processingResults(result: ScanResult) {
        val index =
            deviceList.indexOfFirst { it.device.address == result.device.address }
        if (index != -1) {
            deviceList[index] = result
        } else {
            deviceList.add(result)
        }

        if (deviceList.isNotEmpty()) {

        }
    }

    /**
     * 开始扫描
     */
    fun startBleScan() {
        CoroutineScope(Dispatchers.IO)
            .launch {
                try {
                    callBackNoUI?.scanStatus(1)
                    deviceList.clear()
                    // 创建扫描过滤器
                    val filters: MutableList<ScanFilter> = ArrayList()
                    //只扫描指定打印机
                    val serviceUuid = ParcelUuid.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e")
                    val filter = ScanFilter.Builder().setServiceUuid(serviceUuid).build()
                    filters.add(filter)

                    // 创建扫描设置
                    val settings = ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_BALANCED) // 或其他模式
                        .build()
                    isScanning = true
                    // 开始扫描
                    bleScanner?.startScan(filters, settings, scanCallback)

                    //每次扫描持续15秒
                    delay(15000)

                    //如果扫描结束，没有一个设备就显示缺省
                    if (deviceList.isEmpty()) {
                        callBackNoUI?.scanResult(500,deviceList)
                    }
                    isScanning = false
                    stopBleScan()

                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
    }

    /**
     * 结束扫描
     */
    fun stopBleScan() {
        if (bleAdapter != null && bleAdapter!!.isEnabled) {
            bleScanner?.stopScan(scanCallback)
            callBackNoUI?.scanStatus(2)
        }
    }

    fun connectToBle(device:ScanResult){
        sendEvent(BleToConnectEvent(device.device.address, device.device.name, false))
    }

    fun registeJdqCallBackNoUI(instance:JdqCallBackNoUI){
        callBackNoUI = instance
    }
}